#include "IR.h"
#include "stm32f10x.h"                  // Device header
#include <stdint.h>

uint8_t IR_Address,IR_Command;
static IR_Flag Flag;

/**
  * @brief  红外初始化
  * @param  无
  * @retval 无
  */
void IR_Init()
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
	
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);
	
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line=EXTI_Line15;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel=EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_Init(&NVIC_InitStructure);
	
	/*1us记一次数*/
	TIM_InternalClockConfig(TIM4);
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;		//时钟分频，选择不分频，此参数用于配置滤波器时钟，不影响时基单元功能
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;	//计数器模式，选择向上计数
	TIM_TimeBaseInitStructure.TIM_Period = 65535 - 1;				//计数周期，即ARR的值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 72 - 1;				//预分频器，即PSC的值,预分频值为1则TIM1的频率就是总线APB2的频率
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);
	
	TIM_Cmd(TIM4,DISABLE);	
}

/**
  * @brief  获取红外地址
  * @param  无
  * @retval 接收到的红外地址
  */
uint8_t IR_GetAddress()
{
	if(IR_GetFlag(IR_RX_FLAG)==1||IR_GetFlag(IR_REPEAT_FLAG)==1)
	{
		return IR_Address;
	}
	return 0;
}

/**
  * @brief  获取红外指令
  * @param  无
  * @retval 接收到的红外指令
  */
uint8_t IR_GetCommand()
{
	if(IR_GetFlag(IR_RX_FLAG)==1||IR_GetFlag(IR_REPEAT_FLAG)==1)
	{
		return IR_Command;
	}
	return 0;
}

/**
  * @brief  获取接收标志位
  * @param  Flag：要获取的标志位
  *	 参数可以是这些:
  *   @arg  IR_RX_FLAG        接收标志位
  *   @arg  IR_REPEAT_FLAG    接收重复标志位
  *   @arg  IR_CTRCAR_FLAG    控制小车标志位
  * @retval 获取到的接收标志位
  */
uint8_t IR_GetFlag(uint8_t IR_Flag)
{
	if(IR_Flag==IR_RX_FLAG)
	{
		return Flag.IR_RxDataFlag;
	}
	else if(IR_Flag==IR_REPEAT_FLAG)
	{
		return Flag.IR_RepeatFlag;
	}
	else if(IR_Flag==IR_CTRCAR_FLAG)
	{
		return Flag.IR_CtrCarFlag;
	}
	return 0;
}

/**
  * @brief  红外接收时序
  * @param  无
  * @retval 无
  */
void IR_Prepare()
{
	static uint8_t IR_State=0,IR_Data[4],IR_pData=0;
	static uint32_t IR_Time;
	
	if(IR_State==0)
	{
		TIM_SetCounter(TIM4,0);
		TIM_Cmd(TIM4,ENABLE);
		IR_State=1;
	}
	else if(IR_State==1)
	{
		IR_Time=TIM_GetCounter(TIM4);
		TIM_SetCounter(TIM4,0);
		if(IR_Time>13500-500&&IR_Time<13500+500)
		{
			IR_State=2;
		}
		else if(IR_Time>11250-500&&IR_Time<11250+500)
		{
			Flag.IR_RepeatFlag=1;
			TIM_Cmd(TIM4,ENABLE);
			IR_State=0;
		}
		else
		{
			IR_State=0;
		}
	}
	else if(IR_State==2)
	{
		IR_Time=TIM_GetCounter(TIM4);
		TIM_SetCounter(TIM4,0);
		if(IR_Time>1120-500&&IR_Time<1120+500)
		{
			IR_Data[IR_pData/8]&=~(0x01<<(IR_pData%8));	//数据对应位清0
			IR_pData++;			//数据位置指针自增				
		}
		else if(IR_Time>2250-500&&IR_Time<2250+500)
		{
			IR_Data[IR_pData/8]|=(0x01<<(IR_pData%8));
			IR_pData++;
		}
		else
		{
			IR_pData=0;
			IR_State=0;
		}
		if(IR_pData>=32)
		{
			IR_pData=0;
			if((IR_Data[0]==(char)~IR_Data[1]) && (IR_Data[2]==(char)~IR_Data[3]))  //数据验证(要加上char进行强制类型转换，不然判断可能不正确）
			{
				IR_Address=IR_Data[0];
				IR_Command=IR_Data[2];
				Flag.IR_RxDataFlag=1;
			}
			TIM_Cmd(TIM4,DISABLE);
			IR_State=0;
		}
	}	
}

/**
  * @brief  红外控制小车的运行状态
  * @param  IR_Speed：速度值，一个指向SetMotor_Speed的结构体
  * @retval 无
  */
void IR_CtrMasterCar(SetMotor_Speed* IR_Speed)
{
	if(Flag.IR_RxDataFlag==1||Flag.IR_RepeatFlag==1)  //注意：这里不要用IR_GetFlag和IR_GetRepeatFlag函数，因为主程序中要调用这个函数（如果中断里调用了和主函数里相同的函数，会出现一些问题，如：不能获取到正确的标志位）
	{
		if(IR_Command==IR_POWER)  //小车启动
		{
			Flag.IR_CtrCarFlag=!Flag.IR_CtrCarFlag;
		}
		else if(IR_Command==IR_PREVIOUS&&Flag.IR_CtrCarFlag==1)  //小车向右原地旋转
		{
			IR_Speed->Speed1=100;
			IR_Speed->Speed2=-100;
			IR_Speed->Speed3=100;
			IR_Speed->Speed4=-100;
		}
		else if(IR_Command==IR_NEXT&&Flag.IR_CtrCarFlag==1)  //小车向左原地旋转
		{
			IR_Speed->Speed1=-100;
			IR_Speed->Speed2=100;
			IR_Speed->Speed3=-100;
			IR_Speed->Speed4=100;
		}		
		else if(IR_Command==IR_START_STOP&&Flag.IR_CtrCarFlag==1)  //小车启动/停止
		{
			if(IR_Speed->Speed1==0&&IR_Speed->Speed2==0&&IR_Speed->Speed3==0&&IR_Speed->Speed4==0)
			{
				IR_Speed->Speed1=80;
				IR_Speed->Speed2=80;
				IR_Speed->Speed3=80;
				IR_Speed->Speed4=80;
			}
			else
			{
				IR_Speed->Speed1=0;
				IR_Speed->Speed2=0;
				IR_Speed->Speed3=0;
				IR_Speed->Speed4=0;
			}
		}
		else if(IR_Command==IR_VOL_ADD&&Flag.IR_CtrCarFlag==1)  //加速
		{
			IR_Speed->Speed1+=10;
			IR_Speed->Speed2+=10;
			IR_Speed->Speed3+=10;
			IR_Speed->Speed4+=10;
		}
		else if(IR_Command==IR_VOL_MINUS&&Flag.IR_CtrCarFlag==1)  //减速
		{
			IR_Speed->Speed1-=10;
			IR_Speed->Speed2-=10;
			IR_Speed->Speed3-=10;
			IR_Speed->Speed4-=10;	 	
		}
		else if(IR_Command==IR_1&&Flag.IR_CtrCarFlag==1)  //向左
		{
			IR_Speed->Speed1=0;
			IR_Speed->Speed2=100;
			IR_Speed->Speed3=0;
			IR_Speed->Speed4=100;			
		}
		else if(IR_Command==IR_2&&Flag.IR_CtrCarFlag==1)  //向后
		{
			IR_Speed->Speed1=-70;
			IR_Speed->Speed2=-70;
			IR_Speed->Speed3=-70;
			IR_Speed->Speed4=-70;
		}
		else if(IR_Command==IR_3&&Flag.IR_CtrCarFlag==1)  //向右
		{
			IR_Speed->Speed1=100;
			IR_Speed->Speed2=0;
			IR_Speed->Speed3=100;
			IR_Speed->Speed4=0;	
		}
		
		/*可以在此处添加更多命令
		     ......*/
		
		IR_Command=0; //由于红外发射是连续的，会频繁进入中断，经过我的测试，目前只有在这里将命令的值清0才能有效地避免按键按下无反应（实现Flag.IR_CtrCarFlag的翻转）
					  //但此时无法再获取接收到的命令了，如有需要可以将这一行去掉，单独查看命令
		if(Flag.IR_CtrCarFlag)
		{
			Motor_SetAllSpeed(IR_Speed);
		}
		else if(Flag.IR_CtrCarFlag==0)
		{
			Flag.IR_RepeatFlag=0;
			Flag.IR_RxDataFlag=0;
		}
	}
}

void EXTI15_10_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line15)==SET)
	{
		IR_Prepare();  //红外接收到数据后，对数据进行解码
		
		EXTI_ClearITPendingBit(EXTI_Line15);
	}
}
